package scatter.wxmp.rest.security;

import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.util.WxMpConfigStorageHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Component;
import scatter.common.LoginUser;
import scatter.common.rest.security.LoginUserExtPutService;
import scatter.wxmp.pojo.login.WxMpLoginUser;
import scatter.wxmp.pojo.po.WxMpUser;
import scatter.wxmp.rest.basic.config.MpProperties;
import scatter.wxmp.rest.service.IWxMpUserService;

import javax.swing.text.html.Option;
import java.util.List;
import java.util.Optional;

/**
 * Created by yangwei
 * Created at 2021/1/6 16:59
 */
@Component
@Slf4j
public class WxMpUserDetailsServiceImpl implements UserDetailsService {

    @Autowired
    private WxMpService wxMpService;
    @Autowired
    private MpProperties mpProperties;

    @Autowired
    private IWxMpUserService iWxMpUserService;

    @Autowired(required = false)
    private List<WxMpUserDetailsServiceListener> wxMpUserDetailsServiceListeners;


    @Autowired(required = false)
    private List<LoginUserExtPutService> loginUserExtPutServices;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        // 这里的username实际是code
        String code = username;
        // 在provider中已经switch
        String appId = WxMpConfigStorageHolder.get();
        // 到这里可以获取用户信息了

        WxOAuth2AccessToken wxMpOAuth2AccessToken = null;
        try {
            wxMpOAuth2AccessToken = wxMpService.getOAuth2Service().getAccessToken(code);
        } catch (WxErrorException e) {
            throw new UsernameNotFoundException("网页授权接口调用凭证失败，请检查code是否正确",e);
        }
        boolean valid = wxMpService.getOAuth2Service().validateAccessToken(wxMpOAuth2AccessToken);
        if (!valid) {
            // 刷新token失败，应该重新引导用户授权
            try {
                wxMpOAuth2AccessToken = wxMpService.getOAuth2Service().refreshAccessToken(wxMpOAuth2AccessToken.getRefreshToken());
            } catch (WxErrorException e) {
                throw new UsernameNotFoundException("网页授权token刷新失败",e);
            }
        }
        MpProperties.MpConfig mpConfig = mpProperties.abtainConfigByAppCodeOrAppId(WxMpConfigStorageHolder.get());
        WxOAuth2UserInfo wxMpUser = null;
        try {
            wxMpUser = wxMpService.getOAuth2Service().getUserInfo(wxMpOAuth2AccessToken, null);
        } catch (WxErrorException e) {
            throw new UsernameNotFoundException("网页授权获取用户信息失败",e);
        }
        scatter.wxmp.pojo.po.WxMpUser  byOpenidAndAppCode = iWxMpUserService.getByOpenidAndAppCode(wxMpOAuth2AccessToken.getOpenId(), mpConfig.getAppCode());

        if (byOpenidAndAppCode == null) {
            byOpenidAndAppCode = iWxMpUserService.insert(wxMpUser, mpConfig, scatter.wxmp.pojo.po.WxMpUser.DictSourceItem.wx_mp_user_how_from_oauth2);
        }else {
            scatter.wxmp.pojo.po.WxMpUser mpUser = new scatter.wxmp.pojo.po.WxMpUser();
            mpUser.setId(byOpenidAndAppCode.getId());
            iWxMpUserService.updateById(wxMpUser, mpConfig,mpUser );
        }
        if (byOpenidAndAppCode == null) {
            throw new UsernameNotFoundException("用户信息有问题,这可能是一个bug");
        }
        // 针对具体业务回调
        WxMpUser byId = iWxMpUserService.getById(byOpenidAndAppCode.getId());

        // 处理到这说明没有业务处理登录信息，这里默认处理
        WxMpLoginUser wxMpLoginUser = new WxMpLoginUser();

        // 帐号信息
        wxMpLoginUser.setId(byId.getId());
        wxMpLoginUser.setUsername(byId.getOpenId());
        wxMpLoginUser.setIsEnabled(true);
        wxMpLoginUser.setIsLocked(false);
        wxMpLoginUser.setIsExpired(false);

        // 密码信息
        wxMpLoginUser.setPassword(null);
        wxMpLoginUser.setIsCredentialsExpired(false);

        // 总体信息
        wxMpLoginUser.setWxMpUser(byId);

        // 默认添加用户权限
        wxMpLoginUser.addAuthority("user");

        LoginUser loginUser = null;
        if (wxMpUserDetailsServiceListeners != null) {
            for (WxMpUserDetailsServiceListener wxMpUserDetailsServiceListener : wxMpUserDetailsServiceListeners) {
                loginUser = wxMpUserDetailsServiceListener.onUserInfoReady(byId,appId,wxMpLoginUser);
            }
        }
        LoginUser actualReturn = Optional.ofNullable(loginUser).orElse(wxMpLoginUser);

        // 扩展信息调用
        if (loginUserExtPutServices != null) {
            for (LoginUserExtPutService loginUserExtPutService : loginUserExtPutServices) {
                loginUserExtPutService.addExt(actualReturn);
            }
        }
        return actualReturn;
    }
}
